#define _CRT_SECURE_NO_WARNINGS   1

#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;

class Solution {
public:
	int miniSpanningTree(int n, int m, vector<vector<int>>& cost)
	{
		vector<int> dist(n, INT_MAX);
		vector<int> color(n);
		dist[0] = 0;
		color[0] = 1;
		int current = 0;
		int result = 0;
		vector<vector<int>> edges(n, vector<int>(n, INT_MAX));
		for (int i = 0; i<m; i++){
			edges[cost[i][0] - 1][cost[i][1] - 1] = min(cost[i][2], edges[cost[i][0] - 1][cost[i][1] - 1]);
			edges[cost[i][1] - 1][cost[i][0] - 1] = min(cost[i][2], edges[cost[i][1] - 1][cost[i][0] - 1]);
		}
		for (int i = 1; i<n; i++){
			int mini = INT_MAX;
			int next = 0;
			for (int j = 0; j<n; j++){
				if (color[j] == 0 && edges[current][j]<dist[j]){
					dist[j] = edges[current][j];

				}
				if (mini>dist[j] && color[j] == 0){
					mini = dist[j];
					next = j;
				}

			}
			current = next;
			color[current] = 1;
			result += mini;
		}
		return result;
	}
};

int main()
{
	Solution sol;
	int n;
	int m;
	int num;
	cin >> n >> m;
	vector<vector<int>>a;
	vector<int>v;
	a.clear();
	for (int i = 0; i < n; i++)
	{
		v.clear();
		for (int j = 0; j < m; j++)
		{
			cin >> num;
			v.push_back(num);
		}
		a.push_back(v);
	}
	cout << sol.miniSpanningTree(n, m, a) << endl;
	return 0;
}